package com.harveyspace.aes.social.battlenet;

import com.harveyspace.aes.core.utils.HttpUtil;
import com.harveyspace.aes.core.utils.JsonUtil;
import com.harveyspace.aes.social.Oauth;
import com.harveyspace.aes.social.SocialConfig;
import com.harveyspace.aes.social.exception.SocialException;
import com.harveyspace.aes.social.pojo.AccessTokenInfo;
import com.harveyspace.aes.social.pojo.SocialiteUserInfo;
import com.harveyspace.aes.social.utils.HttpClientSSL;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 战网平台
 *
 * @Author <a href="harveyer@163.com">harvey</a>
 * @date 2018/2/9
 */
public class OauthBattleNet extends Oauth {

    private final String TOKEN_URL = "%s/oauth/token";
    private final String USER_INFO_URL = "%s/oauth/userinfo";

    private BattleNetUserInfo battleNetUserInfo;

    /**
     * @param socialConfig 配置信息
     */
    public OauthBattleNet(SocialConfig socialConfig) {
        super(socialConfig);

        URLEnum urlEnum = URLEnum.get(socialConfig.getRegion());

        AUTH_URL = String.format("%s/oauth/authorize", urlEnum.getGlobalUrl());
    }

    /**
     * 获取授权url
     *
     * @param state OAuth2.0标准协议建议，利用state参数来防止CSRF攻击
     * @return String 返回类型
     */
    @Override
    public String getAuthorizeUrl(String state) {
        return super.getAuthorizeUrl(state);
    }

    /**
     * 获取用户信息
     *
     * @param accessToken AccessToken
     * @return String 返回类型
     */
    private BattleNetUserInfo getUserInfo(String accessToken) throws SocialException {

        Map<String, String> params = new HashMap<>();
        params.put("access_token", accessToken);

        URLEnum urlEnum = URLEnum.get(socialConfig.getRegion());
        String url = String.format(USER_INFO_URL, urlEnum.getApiUrl());

        String result;
        try {
            result = HttpClientSSL.getString(initParams(url, params), null, 45000);
        } catch (Exception e) {
            String errorMessage = String.format("通过 accessToken[%s] 获取用户信息异常", accessToken);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        Map<String, Object> responseMap = JsonUtil.toMap(result);
        String errorCode = MapUtils.getString(responseMap, "error");

        if (StringUtils.isNotBlank(errorCode)) {

            String errorMessage = MapUtils.getString(responseMap, "error_description");

            throw new SocialException(String.format("通过 accessToken[%s] 获取用户信息异常:%s[%s]", accessToken, errorMessage, errorCode));
        }

        return JsonUtil.toObject(result, BattleNetUserInfo.class);
    }

    /**
     * 获取token 返回的是JSON 解析获取到Token以及OpenId
     *
     * @param code 使用code换取token
     * @return String 返回类型
     * @throws SocialException 异常信息
     */
    @Override
    public AccessTokenInfo getAccessToken(String code) throws SocialException {

        Map<String, Object> params = new HashMap<>();
        params.put("code", code);
        params.put("client_id", socialConfig.getClientId());
        params.put("client_secret", socialConfig.getClientSecret());
        params.put("grant_type", "authorization_code");
        params.put("redirect_uri", socialConfig.getRedirectUri());

        URLEnum urlEnum = URLEnum.get(socialConfig.getRegion());
        String url = String.format(TOKEN_URL, urlEnum.getGlobalUrl());
        String result;

        try {
            result = HttpUtil.postString(url, 1, params);
        } catch (IOException e) {
            String errorMessage = String.format("通过 code[%s] 获取 access token异常", code);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        Map<String, Object> responseMap = JsonUtil.toMap(result);
        String errorCode = MapUtils.getString(responseMap, "error");

        if (StringUtils.isNotBlank(errorCode)) {

            String errorMessage = MapUtils.getString(responseMap, "error_description");

            throw new SocialException(String.format("通过 code[%s] 获取 access token异常:%s[%s]", code, errorMessage, errorCode));
        }

        AccessTokenInfo accessTokenInfo = JsonUtil.toObject(result, AccessTokenInfo.class);

        battleNetUserInfo = getUserInfo(accessTokenInfo.getAccessToken());

        accessTokenInfo.setOpenId(battleNetUserInfo.getId());
        accessTokenInfo.setUnionId(battleNetUserInfo.getId());

        return accessTokenInfo;
    }

    @Override
    public SocialiteUserInfo getSocialUserInfo(AccessTokenInfo accessTokenInfo) {

        SocialiteUserInfo socialiteUserInfo = new SocialiteUserInfo();
        socialiteUserInfo.setUnionId(accessTokenInfo.getUnionId());
        socialiteUserInfo.setOpenId(accessTokenInfo.getOpenId());

        if (null != battleNetUserInfo) {
            String name = StringUtils.isNoneBlank(battleNetUserInfo.getBattletag())
                    ? battleNetUserInfo.getBattletag()
                    : "";

            socialiteUserInfo.setNickName(name);
            socialiteUserInfo.setName(name);
        }

        return socialiteUserInfo;
    }
}
